﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SevenZip;
using CMN.Common;
using CMN.Entity;
using CMN.Framework;
using System.IO;
using System.Web;
using System.Net;
using CMN.Models;
using CMN.Models.Interfaces;
using CMN.Framework;
using CMN.Extends.Job;
using CMN.Extends;
using JJ.COMMON;
namespace CMN.Forms
{
    public partial class frmDownload : Form
    {
             
        public bool[] threadStatus { get; set; }    // 每个线程结束标志
        public string[] fileNames { get; set; }     // 每个线程接收文件的文件名
        public int[] StartPos { get; set; }     // 每个线程接收文件的起始位置
        public int[] fileSize { get; set; }         // 每个线程接收文件的大小
        public string Url = "http://downloads5.txt99.com/d/file/p/txt/2015/%E6%9C%80%E6%AF%92%E5%A4%AB%E4%BA%BA%E5%BF%83.txt";             // 接受文件的URL
        public bool HasMerge { get; set; }           // 文件合并标志
        int threadNum = 5; // 进程
        string filePath = "";
        string fileName = "";
        string fileSuffix = "";
        string extractPath = @"F:\C\cmncms\Forms\bin\Release\extract\";
        string CompressionPath = @"F:\C\cmncms\Forms\bin\Release\我的应用\90xz\我的微盘\";
        string downLoadPath = @"F:\C\cmncms\Forms\bin\Release\download\";
        string addPath = @"F:\C\cmncms\Forms\bin\Release\add\";
        Extend_CollectContentEntity collectContent = null;
        bool isStop = false;
        public  int ErrorNum = 0;
        public frmDownload()
        {
            AppLog.Write("frmDownload start", AppLog.LogMessageType.Debug);
            InitializeComponent();
        }
        ~frmDownload()
        {
            isStop = true;
           this.Dispose();
        }
        private void Delete()
        {
            QueryParam qp = new QueryParam();
            qp.ReturnFields = "*";
            qp.Where = " id in ( 668414 )  ";
            IDataService<Extend_CollectContentEntity> Extend_CollectContentSv = ServiceBuilder.BuildExtend_CollectContentService();
            int recoured=0;
            List<Extend_CollectContentEntity> list = Extend_CollectContentSv.List(qp,out recoured);
            for (int i = 0; i < list.Count; i++)
            {
                if (!list[i].IsPass && !string.IsNullOrEmpty(list[i].Img))
                    Utils.DeleteFile(@"F:\C\cmncms\CMN.MvcWeb"+list[i].Img.Replace("/","\\"));
                Extend_CollectContentSv.Delete(list[i]);
                DispMsg(i.ToString());
                System.Threading.Thread.Sleep(20);

            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            //string str = "杀人暗?黑暗馆不死传说（馆系列之七）(书本网).txt";
            //    for(int i=0;i<str.Length;i++)
            //    {
            //        int value = Convert.ToInt32(str[i]);
            //        // Convert the decimal value to a hexadecimal value in string form. 
            //        string hexOutput = String.Format("{0:X}", value);
            //        Console.WriteLine("Hexadecimal value of {0} is {1}", str[i], hexOutput);
            //    }
            //    string str3 = Utils.GetNotEmojiStr(str);
           // Delete();
              startDownLoad();
            
           
        }
        /// <summary>
        /// test
        /// </summary>
        public void startDownLoad2()
        {
            if (isStop)
                return;
            collectContent = new Extend_CollectContentEntity();
            collectContent.SourceFrom = "http://3g.yanqing888.me/Data/25075/";
            collectContent.Remark = "/?a=txt_down&id=25087";

            Url = "http://3g.yanqing888.me/?a=txt_down&id=25043";
            long fileSizeAll = 0;
            if (collectContent.Remark.IndexOf("http") < 0)
                Url = Utils.GetAbsolutePath(collectContent.SourceFrom, collectContent.Remark);
            else
                Url = collectContent.Remark;
            threads = new System.Threading.Thread[threadNum];
            httpDownloads = new HttpMultiThreadDownload[threadNum];
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            fileName = Url.Substring(Url.LastIndexOf("/") + 1, Url.Length - Url.LastIndexOf("/") - 1);
            fileName = Utils.UrlDecode(fileName);
            fileName = fileName.Replace(" ", "");
            fileName = Utils.GetNotEmojiStr(fileName);
            fileName = Utils.ReplaceBadCharOfFileName(fileName);
            fileSuffix = fileName.Substring(fileName.LastIndexOf(".") + 1, fileName.Length - fileName.LastIndexOf(".") - 1);
            if (fileName.IndexOf(".") < 0)
            {
                fileSuffix = "";
                fileName = "";
            }
            try
            {
                fileSizeAll = request.GetResponse().ContentLength;
               // WebHeaderCollection head = request.GetResponse().Headers;
                if (fileName==fileSuffix || string.IsNullOrEmpty(fileSuffix))
                {
                    string str1 = request.GetResponse().Headers["Content-Disposition"];
                    if (!string.IsNullOrEmpty(str1))
                    {
                        string[] strName = str1.Split(new string[] { "=" },StringSplitOptions.RemoveEmptyEntries);
                        if (strName.Length == 2)
                        {
                            fileName = strName[1];
                            fileSuffix = fileName.Substring(fileName.LastIndexOf(".") + 1, fileName.Length - fileName.LastIndexOf(".") - 1);
          
                        }
                    }
                }
               if (fileSizeAll < 1)
               {
                   string str2 = request.GetResponse().Headers["Content-Length"];
                   string str3 = request.GetResponse().Headers["Accept-Length"];
                   if (!string.IsNullOrEmpty(str2))
                       fileSizeAll =long.Parse( str2);
                   if (!string.IsNullOrEmpty(str3))
                       fileSizeAll = long.Parse(str3);
                   
               }
            }
            catch (Exception ex)
            {
                AppLog.Write(Url + ex.Message, AppLog.LogMessageType.Error, ex);

                collectContent.DataTable_Action = DataTableAction.Update;
                collectContent.ViewNum = collectContent.ViewNum + 1;
               
               
            }
            request.Abort();

            Init(fileSizeAll);

            // 定义并启动线程数组

            for (int i = 0; i < threadNum; i++)
            {
                httpDownloads[i] = new HttpMultiThreadDownload(this, i);
                threads[i] = new System.Threading.Thread(new System.Threading.ThreadStart(httpDownloads[i].receive));
                threads[i].Start();
            }
            System.Threading.Thread merge = new System.Threading.Thread(new System.Threading.ThreadStart(MergeFile));
            merge.Start();

        }
        
        public void MoveAndCompressorFile()
        {
            DirectoryInfo directory = null;
            FileInfo[] files = null;
            if (fileSuffix == "rar" || fileSuffix == "zip")
            {
                //解压缩
                try
                {
                    using (SevenZipExtractor tmp = new SevenZipExtractor(filePath))
                    {
                        for (int i = 0; i < tmp.ArchiveFileData.Count; i++)
                        {
                            if (!tmp.ArchiveFileNames[i].EndsWith(".url") && tmp.ArchiveFileNames[i].IndexOf("说明") < 0 && tmp.ArchiveFileNames[i].EndsWith(".txt"))
                            {
                                tmp.ExtractFiles(extractPath, tmp.ArchiveFileData[i].Index);
                            }
                        }
                        //tmp.ExtractFiles(@"d:\temp\!Пусто\", 1, 3, 5); 
                    }
                }
                catch (Exception ex)
                {
                    ErrorNum = ErrorNum + 1;
                    AppLog.Write( ex.Message, AppLog.LogMessageType.Error);
                    File.Delete(filePath);
                    startDownLoad();
                    return;

                }
                  directory = new DirectoryInfo(downLoadPath);
                  files = directory.GetFiles("*.*", SearchOption.AllDirectories);
                foreach (FileInfo var in files)
                {
                        File.Delete(var.DirectoryName + "\\" + var.Name);
                    
                }
            }
            else
            {
                if (!File.Exists(extractPath + fileName))
                    File.Move(filePath, extractPath + fileName);
            }
            //替换网址 重命名
            Common.RegExpression.URLRegExpression URLRg = new CMN.Common.RegExpression.URLRegExpression();

            List<string> fileList = Utils.GetDirectoryFileNames(extractPath, ".txt");
            string strNewName = "";
            string strContent = "";
            Common.RegExpression.RegContext regContent = null;
            Dictionary<string, string> fileDict = new Dictionary<string, string>();
            for (int i = 0; i < fileList.Count; i++)
            {
                if (fileList[i].IndexOf("说明") == -1)
                {

                    strContent = Utils.GetFileContent(fileList[i], Encoding.Default);
                    regContent = new CMN.Common.RegExpression.RegContext(strContent, 'R', "txt.90xz.com");
                    URLRg.Evaluate(regContent);
                    strContent = regContent.Context;
                    Utils.CreateFile(fileList[i], strContent, Encoding.Default);
                    //重命名
                    regContent = new CMN.Common.RegExpression.RegContext(fileList[i], 'R', "");
                    URLRg.Evaluate(regContent);
                    Extend_CollectSetInfoEntity setInfo = CacheCollcetSet.GetSetInfo(collectContent.CollectSetId);

                    strNewName = regContent.Context.Replace(".txt", "");
                    strNewName = CollectHelper.ReplaceArray(strNewName, setInfo.TitleReplaceStr);
                    strNewName = strNewName.Replace(" ", "");
                   // strNewName = Utils.GetNotEmojiStr(strNewName);
                    strNewName = strNewName +"_txt.90xz.com";
                        string fileTemp = strNewName + ".txt";
                        if (!File.Exists(fileTemp))
                            System.IO.File.Move(fileList[i], fileTemp);
                        else
                            File.Delete(fileList[i]);

                }
            }
            //增加自定义压缩内容
             directory = new DirectoryInfo(extractPath);
             files = directory.GetFiles("*.*", SearchOption.AllDirectories);
            
            foreach (FileInfo var in files)
            {
                
                fileDict.Add(var.Name,var.DirectoryName+"\\"+var.Name);
            }
            string SavePath = "";

            SavePath =   DateTime.Now.ToString("yyyy") + "\\" + DateTime.Now.ToString("MM") + "\\" + DateTime.Now.ToString("dd") + "\\" + DateTime.Now.ToString("hh") + "\\"+ strNewName.Substring(strNewName.LastIndexOf("\\")+1,strNewName.Length-1-strNewName.LastIndexOf("\\"))+".zip";
            Utils.CreateDir(Utils.GetMapPath(CompressionPath + SavePath));
            //压缩
            SevenZipCompressor sevenCompressor = new SevenZipCompressor();

            sevenCompressor.CompressionMode = CompressionMode.Create;
            //sevenCompressor.ArchiveFormat = OutArchiveFormat.GZip;
            sevenCompressor.CompressFileDictionary(fileDict,CompressionPath+ SavePath);
            sevenCompressor = null;

            //删除 
           
            directory = new DirectoryInfo(extractPath);
            files = directory.GetFiles("*.txt", SearchOption.AllDirectories);
            foreach (FileInfo var in files)
            {
                if (var.Name.IndexOf("说明") == -1)
                {
                    File.Delete(var.DirectoryName+"\\"+var.Name);
                }
            }
            FileInfo file = new FileInfo(CompressionPath + SavePath);
            collectContent.DataTable_Action = DataTableAction.Update;
            collectContent.IsPass = true;
            collectContent.Size =Utils.ByteConversionGBMBKB( file.Length);
            collectContent.Remark = SavePath + "_|_" + collectContent.Remark;
            IDataService<Extend_CollectContentEntity> Extend_CollectContentSv = ServiceBuilder.BuildExtend_CollectContentService();
            Extend_CollectContentSv.Update(collectContent);
            ErrorNum = 0;
           //循环
            startDownLoad();
        }


       

        System.Threading.Thread[] threads = null;
        HttpMultiThreadDownload[] httpDownloads = null;
        public void startDownLoad()
        {
            if (isStop)
                return;

            QueryParam qp = new QueryParam();
            qp.Orderfld = " id asc ";
            qp.Where = "Enabled=0 and IsPass=0  and ViewNum<4";
            qp.ReturnFields = "*";
            qp.PageSize = 1;
            int recordNum = 0;

            IDataService<Extend_CollectContentEntity> Extend_CollectContentSv = ServiceBuilder.BuildExtend_CollectContentService();
            List<Extend_CollectContentEntity> extend_collectcontentList = Extend_CollectContentSv.List(qp, out recordNum);
            for (int i = 0; i < extend_collectcontentList.Count; i++)
            {
                collectContent = extend_collectcontentList[i];

                threads = new System.Threading.Thread[threadNum];
                httpDownloads = new HttpMultiThreadDownload[threadNum];
                
            }
            if (extend_collectcontentList.Count < 1)
            {
                button1.Enabled = true;
                collectContent = null;
                DispMsg("下载完毕" );
                System.Threading.Thread.Sleep(200);
                return;
            }
          

            DispMsg("正在下载" + collectContent.Title);
            System.Threading.Thread.Sleep(200);
            long fileSizeAll = 0;
            if (string.IsNullOrEmpty(collectContent.Remark) || ErrorNum>=3)
            {
               
                collectContent.DataTable_Action = DataTableAction.Update;
                collectContent.ViewNum = 4;
                Extend_CollectContentSv.Update(collectContent);
                ErrorNum = 0;
                startDownLoad();
               
                return;
                
            }
            if (collectContent.Remark.IndexOf("http") < 0)
                Url = Utils.GetAbsolutePath(collectContent.SourceFrom, collectContent.Remark);
            else
                Url = collectContent.Remark;
          
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            fileName = Url.Substring(Url.LastIndexOf("/") + 1, Url.Length - Url.LastIndexOf("/") - 1);
            fileName = Utils.UrlDecode( fileName);
            fileName = fileName.Replace(" ", "");
            fileName = Utils.GetNotEmojiStr(fileName);
            fileName = Utils.ReplaceBadCharOfFileName(fileName);
            fileSuffix = fileName.Substring(fileName.LastIndexOf(".") + 1, fileName.Length - fileName.LastIndexOf(".") - 1);
            if (fileName.IndexOf(".") < 0)
            {
                fileSuffix = "";
                fileName = "";
            }
            try
            {
                fileSizeAll = request.GetResponse().ContentLength;
                // WebHeaderCollection head = request.GetResponse().Headers;
                if (fileName == fileSuffix || string.IsNullOrEmpty(fileSuffix))
                {
                    string str1 = request.GetResponse().Headers["Content-Disposition"];
                    if (!string.IsNullOrEmpty(str1))
                    {
                        string[] strName = str1.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                        if (strName.Length == 2)
                        {
                            fileName = strName[1];
                            fileSuffix = fileName.Substring(fileName.LastIndexOf(".") + 1, fileName.Length - fileName.LastIndexOf(".") - 1);

                        }
                    }
                }
                if (fileSizeAll < 1)
                {
                    string str2 = request.GetResponse().Headers["Content-Length"];
                    string str3 = request.GetResponse().Headers["Accept-Length"];
                    if (!string.IsNullOrEmpty(str2))
                        fileSizeAll = long.Parse(str2);
                    if (!string.IsNullOrEmpty(str3))
                        fileSizeAll = long.Parse(str3);

                }
            }
            catch (Exception ex)
            {
                request.Abort();
                AppLog.Write(Url+ex.Message, AppLog.LogMessageType.Error, ex);
                
                collectContent.DataTable_Action = DataTableAction.Update;
                collectContent.ViewNum = collectContent.ViewNum + 1;
                Extend_CollectContentSv.Update(collectContent);
                startDownLoad();

                return;
            }
            if (fileSizeAll <=1)
            {

                collectContent.DataTable_Action = DataTableAction.Update;
                collectContent.ViewNum = collectContent.ViewNum + 1;
                Extend_CollectContentSv.Update(collectContent);
                ErrorNum = 0;
                startDownLoad();

                return;

            }
            request.Abort();

            Init(fileSizeAll);

            // 定义并启动线程数组
           
            for (int i = 0; i < threadNum; i++)
            {
                httpDownloads[i] = new HttpMultiThreadDownload(this, i);
                threads[i] = new System.Threading.Thread(new System.Threading.ThreadStart(httpDownloads[i].receive));
                threads[i].Start();
            }
            System.Threading.Thread merge = new System.Threading.Thread(new System.Threading.ThreadStart(MergeFile));
            merge.Start();

        }

        /// <summary>
        /// 定义一个代理
        /// </summary>
        /// <param name="index"></param>
        /// <param name="MSG"></param>
        private delegate void DispMSGDelegate(string MSG);

        /// <summary>
        /// 定义一个函数，用于向窗体上的ListView控件添加内容
        /// </summary>
        /// <param name="iIndex"></param>
        /// <param name="strMsg"></param>
        private void DispMsg(string strMsg)
        {
            if (this.InvokeRequired == false)                      //如果调用该函数的线程和控件lstMain位于同一个线程内
            {
                //直接将内容添加到窗体的控件上

                this.Text = strMsg;
            }
            else                                                        //如果调用该函数的线程和控件lstMain不在同一个线程
            {
                //通过使用Invoke的方法，让子线程告诉窗体线程来完成相应的控件操作
                DispMSGDelegate DMSGD = new DispMSGDelegate(DispMsg);

                //使用控件lstMain的Invoke方法执行DMSGD代理(其类型是DispMSGDelegate)
                this.Invoke(DMSGD, strMsg);

            }
        }


        /// <summary>
        /// 初始化
        /// </summary>
        /// <remarks>
        /// 每个线程平均分配文件大小，剩余部分由最后一个线程完成
        /// </remarks>
        /// <param name="filesize"></param>
        private void Init(long filesize)
        {
            threadStatus = new bool[threadNum];
            fileNames = new string[threadNum];
            StartPos = new int[threadNum];
            fileSize = new int[threadNum];
            int filethread = (int)filesize / threadNum;
            int filethreade = filethread + (int)filesize % threadNum;
            for (int i = 0; i < threadNum; i++)
            {
                threadStatus[i] = false;
                fileNames[i] = i.ToString() + ".dat";
                if (i < threadNum - 1)
                {
                    StartPos[i] = filethread * i;
                    fileSize[i] = filethread - 1;
                }
                else
                {
                    StartPos[i] = filethread * i;
                    fileSize[i] = filethreade - 1;
                }
            }
        }
        /// <summary>
        /// 合并文件
        /// </summary>
        public void MergeFile()
        {
            while (true)
            {
                HasMerge = true;
                for (int i = 0; i < threadNum; i++)
                {
                    if (threadStatus[i] == false) // 若有未结束线程，则等待
                    {
                        HasMerge = false;
                        System.Threading.Thread.Sleep(100);
                        break;
                    }
                }
                if (HasMerge == true) // 否则，停止等待
                    break;
            }

            int bufferSize = 512;
            int readSize;
           
            byte[] bytes = new byte[bufferSize];
            filePath = downLoadPath + fileName;
            FileStream fs = new FileStream(filePath, FileMode.Create);
            FileStream fsTmp = null;

            for (int k = 0; k < threadNum; k++)
            {
                fsTmp = new FileStream(fileNames[k], FileMode.Open);
                while (true)
                {
                    readSize = fsTmp.Read(bytes, 0, bufferSize);
                    if (readSize > 0)
                        fs.Write(bytes, 0, readSize);
                    else
                        break;
                }
                fsTmp.Close();
            }
            fs.Close();
            MoveAndCompressorFile();
        }

     

       
    }
}
